App.require(["htmlTool", "canvasTool"], function (htmlTool, canvasTool) {
    var app = App.getCurrent();

    app.defineLayer("str-text-layer", {
        render: function (next) {
            this.initProperty();
            this.data.isChange = true;
            this.fetch("./index.html", function (text) {
                next(this.renderHTML(text));
            })
        },
        removeOption: function (index) {
            this.data.options.splice(index, 1);
            this.data.isChange = true;
        },
        appendOption: function (option) {
            this.data.options.push(option);
            this.data.isChange = true;
        },
        insertBefore: function (index, option) {
            this.data.options.splice(index, 0, option);
            this.data.isChange = true;
        },
        changeOption: function (index, opt) {
            var option = this.data.options[index];
            if (!option) return;
            for (var key in opt) {
                option[key] = opt[key];
            }
            this.data.isChange = true;
        },
        dispose: function () {
            this.removeAnimation();
            this.data.isChange = true;
            this.data.isMouseIn = false;
        },
        initProperty: function () {
            var property = this.property;
            property.id = property.id || this.uid;
            this.data.isMouseIn = false;

            this.data.options = htmlTool.getOptions(this.slot);
            if (property.animation) this.addPropertyAnimation(property.animation, this);
        },
        createPath: function (ctx, ratio) {},
        _createPath: function (ctx, i, ratio) {
            ctx.save();
            var obj = this.data.options[i], slot = obj.content, font = obj.font || this.font;
            if (obj.x && obj.y) ctx.translate(obj.x * ratio, obj.y * ratio);
            if (obj.rotate) ctx.rotate(obj.rotate);
            if (font) ctx.font = font;
            var width = ctx.measureText(slot).width, x = 0, y = 0, h = ctx.measureText("M").width * 1.1666;
            if (this.align == "end") x -= width;
            else if (this.align == "center") x -= width / 2;

            if (this.baseline == "middle") y -= h / 2;
            else if (this.baseline == "bottom") y -= h;

            ctx.beginPath();
            ctx.rect(x * ratio, y * ratio, width * ratio, h * ratio);
            ctx.restore();
        },
        clickLayerHandler: function (ev, ctx, ratio) {
            var options = this.data.options;
            ctx.translate(this.x * ratio, this.y * ratio);
            for (var i = 0; i < options.length; i++) {
               this._createPath(ctx, i, ratio);
               if (ctx.isPointInPath(ev.clientX * ratio, ev.clientY * ratio)) {
                    this.dispatchCustomEvent("textlayerclick", {
                        index: i,
                        option: options[i],
                        component: this,
                        event: ev
                    });
                   break;
               }
            }
        },
        moveLayerHandler: function (ev, ctx, ratio) {
            var options = this.data.options, isMouseIn = false;
            ctx.translate(this.x * ratio, this.y * ratio);
            for (var i = 0; i < options.length; i++) {
               this._createPath(ctx, i, ratio);
               if (ctx.isPointInPath(ev.clientX * ratio, ev.clientY * ratio)) {
                   isMouseIn = true;
                   if (!this.data.isMouseIn) {
                       this.data.isMouseIn = true;
                       this.dispatchCustomEvent("textlayermouseenter", {
                            index: i,
                            option: options[i],
                            component: this,
                            event: ev
                        });
                        this.data.index = i;
                        break;
                   }
               }
            }

            if (this.data.isMouseIn && !isMouseIn) {
                this.data.isMouseIn = false;
                this.dispatchCustomEvent("textlayermouseleave", {
                    component: this,
                    event: ev,
                    index: this.data.index,
                    data: this.data.options[this.data.index]
                });
            }
        },
        drawSelf: function (ctx, ratio) {
            if (this.data.options.length > 0) {
                var dObj = this.getPropertyUse(["opacity", "x", "y", "shadow", "font", "align", "fill", "stroke", "baseline"]);
                if (typeof dObj.opacity !== "undefined") ctx.globalAlpha = parseFloat(dObj.opacity);
                ctx.translate(dObj.x * ratio, dObj.y * ratio);
                this.transformView(ctx, ratio);
                if (dObj.shadow) this.useShadow(ctx, dObj.shadow, ratio);
                if (dObj.align) ctx.textAlign = dObj.align;
                if (dObj.baseline) ctx.textBaseline = dObj.baseline;
                if (dObj.font) ctx.font = this.computeFont(dObj.font, ratio);
                if (dObj.fill) ctx.fillStyle = this.getFillOrStrokeStyle(dObj.fill);
                if (dObj.stroke) ctx.strokeStyle = this.getFillOrStrokeStyle(dObj.stroke);
                for (var i = 0; i < this.data.options.length; i++) {
                    var obj = this.data.options[i];
                    ctx.save();
                    if (obj.x && obj.y) ctx.translate(parseFloat(obj.x) * ratio, parseFloat(obj.y) * ratio);
                    if (obj.rotate) ctx.rotate(parseFloat(obj.rotate));
                    if (obj.shadow) {
                        var sobj = canvasTool.changeShadowStr(obj.shadow, ratio);
                        if (sobj) {
                            ctx.shadowOffsetX = sobj.x;
                            ctx.shadowOffsetY = sobj.y;
                            ctx.shadowBlur = sobj.blur;
                            ctx.shadowColor = sobj.color;
                        }
                    }
                    if (obj.font) ctx.font = this.computeFont(obj.font, ratio);
                    if (obj.fill || dObj.fill) {
                        if (obj.fill) ctx.fillStyle = this.getFillOrStrokeStyle(obj.fill || dObj.fill);
                        ctx.fillText(obj.content, 0, 0);
                    }
                    if (obj.stroke || dObj.stroke) {
                        if (obj.stroke) ctx.strokeStyle = this.getFillOrStrokeStyle(obj.stroke || dObj.stroke);
                        ctx.strokeText(obj.content, 0, 0);
                    }
                    ctx.restore();
                }
                
            }
        },
        set hidden(value) {
            this.setValue("hidden", value);
        },
        get hidden() {
            return this.getValue("hidden");
        },
        get transform() {
            return this.getValue("transform");
        },
        set transform(value) {
            this.setValue("transform", value);
        },
        get font() {
            return this.getValue("font");
        },
        set font(value) {
            this.setValue("font", value);
        },
        get align() {
            return this.getValue("align");
        },
        set align(value) {
            this.setValue("align", value);
        },
        get fill() {
            return this.getValue("fill");
        },
        set fill(value) {
            this.setValue("fill", value);
        },
        get stroke() {
            return this.getValue("stroke");
        },
        set stroke(value) {
            this.setValue("stroke", value);
        },
        get baseline() {
            return this.getValue("baseline");
        },
        set baseline(value) {
            this.setValue("baseline", value);
        },
        get x() {
            return this.getValue("x");
        },
        set x(value) {
            this.setValue("x", value);
        },
        get y() {
            return this.getValue("y");
        },
        set y(value) {
            this.setValue("y", value);
        },
        get shadow() {
            return this.getValue("shadow");
        },
        set shadow(value) {
            this.setValue("shadow", value);
        },
        get animation() {
            return this.getValue("animation");
        },
        set animation(value) {
            if (this.setValue("animation", value)) {
                if (value) this.addPropertyAnimation(value, this);
            }
        },
        set transition(value) {
            this.setValue("transition", value);
        },
        get transition() {
            return this.getValue("transition");
        },
        set opacity(value) {
            this.setValue("opacity", value);
        },
        get opacity() {
            return this.getValue("opacity");
        }
    })
})